﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using OneSystems.Helpers;

namespace OneSystems.Data.Entities
{
    public partial class Account : BaseEntity<Account>
    {
        #region Public Properties
        /// <summary>
        /// Returns the next due date for the card.
        /// </summary>
        public DateTime NextDueDate
        {
            get
            {
                DateTime returnValue =  DateTime.Parse(string.Format("{0}/{1}/{2}", DateTime.Today.Month, DueDay, DateTime.Today.Year));
                if (returnValue < DateTime.Today)
                {
                   returnValue = returnValue.AddMonths(1);
                }
                return returnValue;
            }

        }
        /// <summary>
        /// Nickname on the account.
        /// </summary>
        public string AccountNickname
        {
            get
            {
                return Nickname;
            }
        }
        public decimal CashAdvanceRate
        {
            get
            {
                Rate rate = GetActiveRate(PublicEnums.TransactionTypes.CashAdvance);
                return rate != null ? rate.InterestRate : 0;
            }
            set
            {
                SetActiveRate(value, PublicEnums.TransactionTypes.CashAdvance);
            }
        }
        public decimal InterestRate
        {
            get
            {
                OneSystems.Data.Entities.Rate rate = GetActiveRate(PublicEnums.TransactionTypes.Charge);
                return rate != null ? rate.InterestRate : 0;
            }
            set
            {
                SetActiveRate(value, PublicEnums.TransactionTypes.Charge);
            }
        }
        public decimal CreditLimit
        {
            get
            {
                OneSystems.Data.Entities.CreditLimit creditLimit = GetActiveLimit();
                return creditLimit != null ? creditLimit.Amount : 0;
            }
            set
            {
                SetActiveLimit(value);
            }
        }
        public decimal CurrentBalance
        {
            get
            {
                return GetCurrentBalance();
            }
        }
        public decimal MinPayment
        {
            get
            {
                return GetMinimumPayment();
            }
        }
        public System.Drawing.Image Logo
        {
            get
            {
                Image logo = Category.Logo;
                if (Brand != null)
                {
                    logo = Brand.Logo;
                }
                return logo;
            }
        }

        public List<Transaction> FutureTransactions
        {
            get
            {
                return GetFutureTransactions(0);
            }
        }
        #endregion

        #region Manage limits and Interest
        
        private decimal GetCurrentBalance()
        {
            decimal currentBalance = 0;

            var credits = from p in Transactions
                          where p.TransactionType.Operation == '+'
                          select p;
            var debits = from p in Transactions
                         where p.TransactionType.Operation == '-'
                         select p;

            currentBalance += credits.Sum(c => c.Amount);
            currentBalance -= debits.Sum(c => c.Amount);

            return currentBalance;
        }
        private decimal GetMinimumPayment()
        {
            decimal minimumPayment = 0;
            minimumPayment = CurrentBalance * PaymentPercentage;
            minimumPayment = minimumPayment > MinimumPayment ? minimumPayment : MinimumPayment;

            return minimumPayment;
        }
        private Rate GetActiveRate(PublicEnums.TransactionTypes transactionTypeID)
        {
            OneSystems.Data.Entities.Rate rate = null;

            if (Rates.Where(c => c.TransactionTypeID == (int)transactionTypeID).Count() > 0)
            {
                rate = Rates.Where(c => c.TransactionTypeID == (int)transactionTypeID).OrderByDescending(c => c.RateID).First();
            }
            return rate;
        }
        private CreditLimit GetActiveLimit()
        {
            OneSystems.Data.Entities.CreditLimit creditLimit = null;

            if (CreditLimits.Count > 0)
            {
                creditLimit = CreditLimits.OrderByDescending(c => c.CreditLimitID).First();
            }
            return creditLimit;
        }
        private void SetActiveRate(decimal newRate, PublicEnums.TransactionTypes transactionTypeID)
        {
            Rate rateHolder = GetActiveRate(transactionTypeID);

            if (rateHolder == null || rateHolder.InterestRate != newRate)
            {
                CreateRate(newRate, transactionTypeID);
            }
        }
        private void SetActiveLimit(decimal newLimit)
        {
            CreditLimit creditLimit = GetActiveLimit();

            if (creditLimit == null || creditLimit.Amount != newLimit)
            {
                CreateLimit(newLimit);
            }
        }
        private void CreateRate(decimal newRate, PublicEnums.TransactionTypes transactionTypeID)
        {
            Rate rateItem = new Rate();
            rateItem.AccountID = AccountID;
            rateItem.InterestRate = newRate;
            rateItem.EffectiveDate = DateTime.Today;
            rateItem.Active = true;
            rateItem.TransactionTypeID = (int)transactionTypeID;
            rateItem.Save();
        }
        private void CreateLimit(decimal newLimit)
        {
            CreditLimit limitItem = new CreditLimit();
            limitItem.AccountID = AccountID;
            limitItem.Amount = newLimit;
            limitItem.BeginDate = DateTime.Today;
            limitItem.Active = true;
            limitItem.Save();
        }
        public List<Transaction> GetFutureTransactions(decimal pledgeAmount)
        {
            List<Transaction> futureTransactions = new List<Transaction>();
            decimal balance = CurrentBalance;
            DateTime firstFuturePayment = NextDueDate;

            while (balance > 0)
            {
                Transaction transaction = new Transaction();
                transaction.Occurred = firstFuturePayment;
                transaction.TransactionTypeID = (int)OneSystems.Helpers.PublicEnums.TransactionTypes.Payment;

                if (balance < MinimumPayment)
                {
                    transaction.Amount = balance;
                }
                else
                {
                    transaction.Amount = balance * PaymentPercentage;
                    if (transaction.Amount < MinimumPayment)
                    {
                        transaction.Amount = MinimumPayment;
                    }
                }
                transaction.Amount = Math.Round(transaction.Amount, 0);
                transaction.Amount += pledgeAmount;
                decimal interest = Math.Round(balance * InterestRate / 12, 2);
                balance = balance += interest;
                balance = balance -= transaction.Amount;
                if (balance < 0)
                {
                    balance = 0;
                }
                transaction.AccountID = AccountID;
                transaction.Payee = Creditor.Name;

                futureTransactions.Add(transaction);
                firstFuturePayment = firstFuturePayment.AddMonths(1);

            }
            return futureTransactions;
        }
        #endregion
    }
}
